package com.microservice.base.task;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.microservice.base.entity.*;
import com.microservice.base.mapper.hikcommon.CHkCameraMapper;
import com.microservice.base.mapper.hikcommon.CHkRecordsMapper;
import com.microservice.base.mapper.hikcommon.CHkRegionMapper;
import com.microservice.base.mapper.smart.CPassThirdTraceMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author jbx
 * @package_name com.microservice.base.task
 * @create_date 2020/12/21 13:12
 */
@Component
@Transactional
@EnableScheduling
public class syncRecords {
    @Autowired
    CHkRecordsMapper cHkRecordsMP;
    @Autowired
    CPassThirdTraceMapper cPassThirdTraceMP;
    Logger logger = LoggerFactory.getLogger(syncData.class);
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS+8:00");

    @Value("${schoolcode}")
    private String schoolCode;
    @Autowired
    CHkCameraMapper cameraMP;
    @Autowired
    CHkRegionMapper regionMP;

    @Scheduled(cron = "0 0/10 * * * ?")
    public void sync() {
        try {
            // 将监控点信息和区域信息拉取到本地数据库
            cameraAdd();
            regionAdd();
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error(e + "拉取海康监控点,区域数据出现异常");
        }
        // 拉取人员记录信息
        // 先查询本地数据库里是否有数据,因为数据量庞大,所以只查询第一条数据是否存在
        List<CHkRecords> cHkRecords = cHkRecordsMP.queryAllByLimit();
        if (cHkRecords.size() > 0) {
            // 当第一次无数据循环完成或者发生故障重启后进行的操作
            // startTime = 上一次的系统时间+1毫秒,endTime = 本次的系统时间,注意时间点的开闭区间
            // 因为海康时间的最小单位是毫秒,故只需要哦加上1毫秒即可
            // 海康时间的规则为: starttime<= 查询信息 <=endtime
            Map<String, Date> maxEndTime = cHkRecordsMP.getMaxEndTime();
            Date startTime = new Date(maxEndTime.get("lastSysTime").getTime() + 1);
            Date endTime = new Date();
            int pageNo = 1;
            Integer total;
            List<CHkRecords> saveList = new ArrayList<>();
            try {
                do {
                    JSONObject jo = new JSONObject();
                    jo.put("startTime", simpleDateFormat.format(startTime));
                    jo.put("endTime", simpleDateFormat.format(endTime));
                    jo.put("similarity", 80);
                    jo.put("pageSize", 1000);
                    jo.put("pageNo", pageNo);
                    String s = HikConnection.pushHik("/api/frs/v1/event/black/search", jo.toString());
                    JSONObject jsonObject = JSONObject.parseObject(s);
                    JSONObject data = jsonObject.getJSONObject("data");
                    total = data.getInteger("total");
                    JSONArray recordslist = data.getJSONArray("list");
                    for (int i = 0; i < recordslist.size(); i++) {
                        JSONObject listObject = recordslist.getJSONObject(i);
                        JSONObject snapInfo = listObject.getJSONObject("snapInfo");
                        List<TargetInfo> targetInfoList =
                                listObject.getJSONArray("targetInfoList").toJavaList(TargetInfo.class);
                        tranCHKrecord(startTime, endTime, saveList, snapInfo, targetInfoList);
                    }
                    pageNo += 1;
                } while (total > (pageNo - 1) * 1000);
                if (saveList.size() > 0) {
                    for (int i = 0; i <= saveList.size() / 1000; i++) {
                        cHkRecordsMP.saveBatch(saveList.stream().skip(i * 1000).collect(Collectors.toList()));
                    }
                }
                logger.error("拉取records数据成功");
            } catch (Exception e) {
                logger.error("拉取records数据出错:" + e);
            }

            try {
                // 数据量很大,删除3天前的数据
                cHkRecordsMP.deleteBeforeThreeDays();
                logger.error("删除三天前数据成功....");
            } catch (Exception e) {
                logger.error("删除三天前数据失败," + e);
            }

        } else {
            // 本地数据库无数据,starttime=表中最大时间,endtime=当前系统时间
            Calendar calendar = Calendar.getInstance();
            // 设置将从2020年12月01号以来的数据全部拿到
            calendar.set(2021, 06, 01);
            Date startTime = calendar.getTime();
            Date endTime = new Date();
            int pageNo = 1;
            Integer total;
            List<CHkRecords> saveList = new ArrayList<>();
            try {
                do {
                    JSONObject jo = new JSONObject();
                    jo.put("startTime", simpleDateFormat.format(startTime));
                    jo.put("endTime", simpleDateFormat.format(endTime));
                    jo.put("similarity", 80);
                    jo.put("pageSize", 1000);
                    jo.put("pageNo", pageNo);
                    String s = HikConnection.pushHik("/api/frs/v1/event/black/search", jo.toString());
                    JSONObject jsonObject = JSONObject.parseObject(s);
                    JSONObject data = jsonObject.getJSONObject("data");
                    total = data.getInteger("total");
                    JSONArray recordslist = data.getJSONArray("list");
                    for (int i = 0; i < recordslist.size(); i++) {
                        JSONObject listObject = recordslist.getJSONObject(i);
                        JSONObject snapInfo = listObject.getJSONObject("snapInfo");
                        List<TargetInfo> targetInfoList =
                                listObject.getJSONArray("targetInfoList").toJavaList(TargetInfo.class);
                        tranCHKrecord(startTime, endTime, saveList, snapInfo, targetInfoList);
                    }
                    pageNo += 1;
                } while (total > (pageNo - 1) * 1000);
                if (saveList.size() > 0) {
                    for (int i = 0; i <= saveList.size() / 1000; i++) {
                        cHkRecordsMP.saveBatch(saveList.stream().skip(i * 1000).limit(1000).collect(Collectors.toList()));
                    }
                }
                logger.error("拉取records数据成功");
            } catch (Exception e) {
                logger.error("拉取records数据出错:" + e);
            }
            // 等于1000说明后面还有数据,继续循环拿取数据
        }

        // 进行智慧管理库的同步
        // 拉取的规则,insertinto全部sync_flag=0的数据,拉取结束后,将sync_flag置为1
        List<CPassThirdTrace> cPassThirdTraceList = cHkRecordsMP.getTraceBySyncFlag(0);
        List<CHkRecords> recordsBySyncFlag = cHkRecordsMP.getBySyncFlag(0);

        List<CPassThirdTrace> addDbThirdTrace = new ArrayList<>();
        List<CHkRecords> addDbRecord = new ArrayList<>();
        for (CPassThirdTrace cPassThirdTrace : cPassThirdTraceList) {
            cPassThirdTrace.setId(UUID.randomUUID().toString().replace("-", ""));
            if ("male".equals(cPassThirdTrace.getUserSex())) {
                cPassThirdTrace.setUserSex("1");
            } else if ("female".equals(cPassThirdTrace.getUserSex())) {
                cPassThirdTrace.setUserSex("2");
            } else {
                cPassThirdTrace.setUserSex("0");
            }
            // 抓拍分类,自定义名称"TRACk"
            cPassThirdTrace.setPassType("TRACK");
            cPassThirdTrace.setDiscrenType("2");
            cPassThirdTrace.setDataSource("hikvision");
            cPassThirdTrace.setDeleted("0");
            cPassThirdTrace.setStatus("1");
            cPassThirdTrace.setUpdateTime(new Date());
            addDbThirdTrace.add(cPassThirdTrace);
        }
        for (CHkRecords updateRecord : recordsBySyncFlag) {
            updateRecord.setSyncFlag(1);
            addDbRecord.add(updateRecord);
        }
        // 进行批量插入,插入完之后更新原有数据的sync_flag
        if (addDbThirdTrace.size() > 0) {
            for (int i = 0; i <= addDbThirdTrace.size() / 2000; i++) {
                cPassThirdTraceMP.saveBatch(
                        addDbThirdTrace.stream().skip(i * 2000).limit(2000).collect(Collectors.toList()));
            }
            for (int i = 0; i <= addDbRecord.size() / 1000; i++) {
                cHkRecordsMP.saveBatch(
                        addDbRecord.stream().skip(i * 1000).limit(1000).collect(Collectors.toList()));
            }
            logger.error("同步到云端行为轨迹成功!,一共:" + addDbThirdTrace.size());
        }
    }

    public void tranCHKrecord(
            Date startTime,
            Date endTime,
            List<CHkRecords> saveList,
            JSONObject snapInfo,
            List<TargetInfo> targetInfoList)
            throws ParseException {
        CHkRecords saveRecord = new CHkRecords();
        saveRecord.setId(UUID.randomUUID().toString().replace("-", ""));
        saveRecord.setSyncFlag(0);
        saveRecord.setStarttime(startTime);
        saveRecord.setEndtime(endTime);
        saveRecord.setBgkUrl((String) snapInfo.get("bkgUrl"));
        saveRecord.setSnapUrl((String) snapInfo.get("snapUrl"));
        saveRecord.setCameraindexCode((String) snapInfo.get("cameraIndexcode"));
        saveRecord.setCameraName((String) snapInfo.get("cameraName"));
        saveRecord.setEventtime(hikDate(snapInfo.get("eventTime").toString()));
        for (TargetInfo targetInfo : targetInfoList) {
            saveRecord.setName(targetInfo.getName());
            saveRecord.setSex(targetInfo.getSex());
            saveRecord.setSimilarity(targetInfo.getSimilarity());
            saveRecord.setCertificateType(targetInfo.getCertificateType());
            saveRecord.setCertificateNumber(targetInfo.getCertificateNumber());
            saveRecord.setFaceUrl(targetInfo.getFaceUrl());
            saveRecord.setFaceinfoindexCode(targetInfo.getFaceInfoIndexcode());
            saveList.add(saveRecord);
        }
    }

    public Date hikDate(String date) throws ParseException {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String replace = date.substring(0, 18).replace("T", " ");
        Date parse = simpleDateFormat.parse(replace);
        return parse;
    }

    public void cameraAdd() {
        JSONObject jo = new JSONObject();
        jo.put("pageNo", "1");
        jo.put("pageSize", "1000");
        String s = HikConnection.pushHik("/api/resource/v2/camera/search", jo.toJSONString());
        JSONObject jsonObject = JSONObject.parseObject(s);
        JSONObject data = jsonObject.getJSONObject("data");
        if (data.getInteger("total") != 0) {
            List<CHkCamera> cameraList = data.getJSONArray("list").toJavaList(CHkCamera.class);
            // 获取cameraLists
//      cameraMP.truncateTable();
            for (CHkCamera chkcamera : cameraList) {
                chkcamera.setDeleted("0");
                cameraMP.save(chkcamera);
            }
            logger.error("拉取成功所有监控信息" + cameraList);
        } else {
            logger.error("没有需要拉取的监控信息");
        }
    }

    public void regionAdd() {
        JSONObject jo = new JSONObject();
        jo.put("pageNo", "1");
        jo.put("pageSize", "1000");
        jo.put("resourceType", "region");
        String s = HikConnection.pushHik("/api/irds/v2/region/nodesByParams", jo.toJSONString());
        JSONObject jsonObject = JSONObject.parseObject(s);
        JSONObject data = jsonObject.getJSONObject("data");
        if (data.getInteger("total") != 0) {
            List<CHkRegion> regionList = data.getJSONArray("list").toJavaList(CHkRegion.class);
//      regionMP.truncateTable();
            for (CHkRegion cHkRegion : regionList) {
                cHkRegion.setDeleted("0");
                regionMP.save(cHkRegion);
            }
            logger.error("拉取成功所有区域信息" + regionList);
        } else {
            logger.error("没有需要拉取的区域信息");
        }
    }
}
